package org.openkanban.client.ui.board;

import org.openkanban.client.cometd.CometClient;
import org.openkanban.client.cometd.SubscribeCallback;
import org.openkanban.client.ui.presenter.GetKanbanByIdRequestCallback;
import org.openkanban.client.ui.presenter.PreparedRequest;
import org.openkanban.client.ui.presenter.RemoveKanbanRequestCallback;
import org.openkanban.client.ui.presenter.ToggleKanbanRequestCallback;
import org.openkanban.client.util.RootPanel;
import org.openkanban.shared.dto.KanbanDto;

import com.google.gwt.core.client.JavaScriptObject;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.BkgndRepeat;
import com.smartgwt.client.types.DragAppearance;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.JSON;
import com.smartgwt.client.util.Page;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.DoubleClickEvent;
import com.smartgwt.client.widgets.events.DoubleClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.Layout;
import com.smartgwt.client.widgets.layout.VLayout;

/**
 * GUI Element for the KanbanView
 */
public class KanbanView extends Canvas {

    private Label titleLabel;

    private VLayout mainLayout;

    private IButton pullableButton;

    private Long parentActivityId;
    private KanbanDto kanbanDto;
    private ToggleKanbanRequestCallback toggleKanbanRequestCallback;
    private RemoveKanbanRequestCallback removeKanbanRequestCallback;
    private HLayout kanbanHeaderHLayout;
    private HLayout kanbanFooterHLayout;
    private Label effortLabel;
    private Label effortNameLabel;

    private IButton removeButton;

    private CometClient cometClient;

    public KanbanView(Long parentActivityId) {
	cometClient = RootPanel.main.getCometClient();

	this.parentActivityId = parentActivityId;

	toggleKanbanRequestCallback = new ToggleKanbanRequestCallback(this);
	removeKanbanRequestCallback = new RemoveKanbanRequestCallback(this);

	pullableButton = new IButton();
	pullableButton.setWidth(40);
	pullableButton.setHeight(10);
	pullableButton.setSrc(Page.getAppImgDir() + "kanban/pullok.png");
	pullableButton.addClickHandler(new ClickHandler() {
	    @Override
	    public void onClick(ClickEvent event) {
		kanbanDto.setPullable(!kanbanDto.getPullable());

		PreparedRequest prepReq = new PreparedRequest("kanban", "update", kanbanDto);
		prepReq.sendAsyncRequest(toggleKanbanRequestCallback);
	    }
	});

	removeButton = new OpenKanbanButton("-");
	removeButton.setWidth(15);
	removeButton.setHeight(15);
	removeButton.addClickHandler(new ClickHandler() {
	    @Override
	    public void onClick(ClickEvent event) {
		SC.confirm("Do you really want to remove this kanban?", new BooleanCallback() {
		    @Override
		    public void execute(Boolean value) {
			if (value != null && value) {
			    PreparedRequest prepReq = new PreparedRequest("kanban", kanbanDto.getKanbanId().toString() + "/remove");
			    prepReq.sendAsyncRequest(removeKanbanRequestCallback);
			}
		    }
		});
	    }
	});

	titleLabel = new Label();
	titleLabel.setAutoHeight();
	titleLabel.setWidth100();
	titleLabel.setAlign(Alignment.LEFT);
	titleLabel.setValign(VerticalAlignment.TOP);
	titleLabel.setMargin(2);
	titleLabel.setStyleName("kanbanTitle");

	effortNameLabel = new Label("Effort: ");
	effortNameLabel.setAutoWidth();
	effortNameLabel.setAutoHeight();
	effortNameLabel.setAlign(Alignment.RIGHT);
	effortNameLabel.setStyleName("kanbanEffortName");

	effortLabel = new Label();
	effortLabel.setAutoWidth();
	effortLabel.setAutoHeight();
	effortLabel.setAlign(Alignment.RIGHT);
	effortLabel.setValign(VerticalAlignment.TOP);
	effortLabel.setStyleName("kanbanEffort");

	Layout headerPlaceholderHLayout = new Layout();
	headerPlaceholderHLayout.setWidth100();
	Layout footerPlaceholderHLayout = new Layout();
	footerPlaceholderHLayout.setWidth100();

	kanbanHeaderHLayout = new HLayout();
	kanbanHeaderHLayout.addMember(removeButton);
	kanbanHeaderHLayout.addMember(headerPlaceholderHLayout);
	kanbanHeaderHLayout.addMember(pullableButton);

	kanbanFooterHLayout = new HLayout();
	kanbanFooterHLayout.addMember(footerPlaceholderHLayout);
	kanbanFooterHLayout.addMember(effortNameLabel);
	kanbanFooterHLayout.addMember(effortLabel);

	mainLayout = new VLayout();
	mainLayout.setAutoHeight();
	mainLayout.setWidth100();

	mainLayout.addMember(kanbanHeaderHLayout);
	mainLayout.addMember(titleLabel);
	mainLayout.addMember(kanbanFooterHLayout);

	// kanban view properties
	setAutoHeight();
	setDragType("kanban");

	setBackgroundImage("corners/kanban_C.png");
	setBackgroundRepeat(BkgndRepeat.REPEAT);

	setStyleName("kanban");
	setShowEdges(true);
	setEdgeImage("corners/kanban.png");
	setEdgeSize(15);
	setDragAppearance(DragAppearance.TARGET);
	setShowDragShadow(true);
	setShadowOffset(0);

	setCanDrag(true);
	setCanDragReposition(true);
	setCanDrop(true);
	setShowHover(false);

	addDoubleClickHandler(kanbanViewDoubleClickHandler(this));

	addChild(mainLayout);
    }

    public KanbanView(KanbanDto kanbanDto, Long parentActivityId) {
	this(parentActivityId);
	this.kanbanDto = kanbanDto;

	titleLabel.setContents(kanbanDto.getTitle());
	effortLabel.setContents(kanbanDto.getEffort());
	togglePullableButton();

	setTitle(kanbanDto.getKanbanId().toString());

	subscribe();
    }

    public void subscribe() {
	cometClient.subscribe("/kanban/" + kanbanDto.getKanbanId().toString(), new SubscribeCallback() {
	    @Override
	    public void execute(JavaScriptObject jso) {
		updateKanbanDto();
	    }
	});
    }

    public void publish() {
	cometClient.publish("/kanban/" + kanbanDto.getKanbanId().toString(), JSON.decode("{}"));
    }

    public void updateKanbanDto() {
	PreparedRequest prepReq = new PreparedRequest("kanban", kanbanDto.getKanbanId().toString());
	prepReq.sendAsyncRequest(new GetKanbanByIdRequestCallback(this));
    }

    private DoubleClickHandler kanbanViewDoubleClickHandler(final KanbanView kanbanView) {
	return new DoubleClickHandler() {
	    @Override
	    public void onDoubleClick(DoubleClickEvent event) {
		RootPanel.activateEditKanbanMode(true, kanbanView);
	    }
	};
    }

    public void togglePullableButton() {
	if (kanbanDto.getPullable()) {
	    pullableButton.setSrc(Page.getAppImgDir() + "kanban/pullok.png");
	} else {
	    pullableButton.setSrc(Page.getAppImgDir() + "kanban/pullnok.png");
	}
    }

    public Label getTitleLabel() {
	return titleLabel;
    }

    public void setTitleLabel(Label titleLabel) {
	this.titleLabel = titleLabel;
    }

    public KanbanDto getKanbanDto() {
	return kanbanDto;
    }

    public void setKanbanDto(KanbanDto kanbanDto) {
	this.kanbanDto = kanbanDto;
	titleLabel.setContents(kanbanDto.getTitle());
	effortLabel.setContents(kanbanDto.getEffort());
	togglePullableButton();
    }

    public Long getParentActivityId() {
	return parentActivityId;
    }

    public void setParentActivityId(Long parentActivityId) {
	this.parentActivityId = parentActivityId;
    }

    public boolean isReadyForPull() {
	return kanbanDto.getPullable();
    }

}